//
// Copyright (C) 2011 Steve Channell steve.channell@cepheis.com
//
// This file is part of Cephei.QL, an open-source library wrapper 
// arround QuantLib http://quantlib.org/
//
// Cephei.QL is open source software: you can redistribute it and/or modify it
// under the terms of the license.  You should have received a
// copy of the license along with this program; if not, please email
// <support@cepheis.com>. The license is also available online at
// <http://cepheis.com/license.htm>.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the license for more details.
//
// Version 2.101
//#include "stdafx.h"
#include "CommodityPricingHelper.h"
using namespace Cephei::QL::Experimental::Commodities;
#include <gen/QL/Currency.h>
#include <gen/QL/Experimental/Commodities/CommodityType.h>
#include <gen/QL/Experimental/Commodities/CommodityUnitCost.h>
#include <gen/QL/Experimental/Commodities/UnitOfMeasure.h>
#include <gen/QL/Experimental/Commodities/Quantity.h>
#include <gen/QL/Experimental/Commodities/PaymentTerm.h>
#include <gen/QL/Experimental/Commodities/PricingPeriod.h>
using namespace Cephei::QL;
#undef HANDLE
#undef ABSTRACT
#undef STRUCT
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper () 
{
	_pSpinlock = new boost::detail::spinlock ();
    try
    {
#ifdef HANDLE
        _phCommodityPricingHelper = NULL;
#endif
        _ppCommodityPricingHelper = new boost::shared_ptr<QuantLib::CommodityPricingHelper> (new QuantLib::CommodityPricingHelper ( ));
        
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown std::exception"));
	}
    finally
    {
    }
}
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper (boost::shared_ptr<QuantLib::CommodityPricingHelper>& childNative, Object^ owner) 
{
	_pSpinlock = new boost::detail::spinlock ();
#ifdef HANDLE
	_phCommodityPricingHelper = NULL;
#endif
	_ppCommodityPricingHelper = &childNative;
    
}
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper (QuantLib::CommodityPricingHelper& childNative, Object^ owner) 
{
#ifdef HANDLE
	_phCommodityPricingHelper = NULL;
#endif
	_ppCommodityPricingHelper = new boost::shared_ptr<QuantLib::CommodityPricingHelper> (&childNative);
    
    _CommodityPricingHelperOwner = owner;
    
}

Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper (CCommodityPricingHelper^ copy) 
{
	_pSpinlock = new boost::detail::spinlock ();
#ifdef HANDLE
	_phCommodityPricingHelper = NULL;
#endif
	if (copy->HasNative() != NULL)
    {
		_ppCommodityPricingHelper = new boost::shared_ptr<QuantLib::CommodityPricingHelper> (copy->GetShared());
        
    }
}
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper (System::Type^ t) 
{
	_pSpinlock = new boost::detail::spinlock ();
#ifdef HANDLE
	_phCommodityPricingHelper = NULL;
#endif
	if (!t->IsSubclassOf(CCommodityPricingHelper::typeid))
		throw gcnew Exception ("Invalid base-case init");
}
#ifdef HANDLE
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper (QuantLib::Handle<QuantLib::CommodityPricingHelper>& childNative, Object^ owner)  
{
	_pSpinlock = new boost::detail::spinlock ();
	_phCommodityPricingHelper = &childNative;
	_ppCommodityPricingHelper = &static_cast<boost::shared_ptr<QuantLib::CommodityPricingHelper>>(childNative.currentLink());
    
    _CommodityPricingHelperOwner = owner;
}
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper (QuantLib::Handle<QuantLib::CommodityPricingHelper> childNative)  
{
	_pSpinlock = new boost::detail::spinlock ();
	_phCommodityPricingHelper = &childNative;
	_ppCommodityPricingHelper = &static_cast<boost::shared_ptr<QuantLib::CommodityPricingHelper>>(childNative.currentLink());
    
}
#endif
#ifdef STRUCT
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CCommodityPricingHelper (QuantLib::CommodityPricingHelper childNative)  
{
	_pSpinlock = new boost::detail::spinlock ();
#ifdef HANDLE
	_phCommodityPricingHelper = NULL;
#endif
	_ppCommodityPricingHelper = new boost::shared_ptr<QuantLib::CommodityPricingHelper> (new QuantLib::CommodityPricingHelper (childNative));
    
}
#endif

Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::~CCommodityPricingHelper ()
{
	if (_pSpinlock != NULL)
    {
        delete _pSpinlock;
        _pSpinlock = NULL;
    }
    if (_ppCommodityPricingHelper != NULL)
    {
	    delete _ppCommodityPricingHelper;
        _ppCommodityPricingHelper = NULL;
    }
}
Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::!CCommodityPricingHelper ()
{
	if (_pSpinlock != NULL)
    {
        delete _pSpinlock;
    }
    if (_ppCommodityPricingHelper != NULL)
    {
	    delete _ppCommodityPricingHelper;
    }
}
QuantLib::CommodityPricingHelper& Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::GetReference ()
{
    if (_ppCommodityPricingHelper == NULL) throw gcnew NativeNullException ();
	return **_ppCommodityPricingHelper;
}
boost::shared_ptr<QuantLib::CommodityPricingHelper>& Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::GetShared ()
{
    if (_ppCommodityPricingHelper == NULL) throw gcnew NativeNullException ();
	return *_ppCommodityPricingHelper;
}
QuantLib::CommodityPricingHelper* Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::GetPointer ()
{
    if (_ppCommodityPricingHelper == NULL) throw gcnew NativeNullException ();
	return &**_ppCommodityPricingHelper;
}
#ifdef HANDLE
QuantLib::Handle<QuantLib::CommodityPricingHelper>& Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::GetHandle ()
{
	if (_phCommodityPricingHelper == NULL)
	{
		_phCommodityPricingHelper = new Handle<QuantLib::CommodityPricingHelper> (*_ppCommodityPricingHelper);
	}
	return *_phCommodityPricingHelper;
}
#endif
bool Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::HasNative () 
{
	return (_ppCommodityPricingHelper != NULL);
}

Double Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CalculateFxConversionFactor (Cephei::QL::ICurrency^ fromCurrency, Cephei::QL::ICurrency^ toCurrency, DateTime evaluationDate)
{
    CCurrency^ _CfromCurrency;
    CCurrency^ _CtoCurrency;
    try
    {
    	boost::detail::spinlock::scoped_lock lock (*_pSpinlock);
        _CfromCurrency = safe_cast<CCurrency^> (fromCurrency);
        _CfromCurrency->Lock();
        QuantLib::Currency& _fromCurrency = static_cast<QuantLib::Currency&> (_CfromCurrency->GetReference ()); 
        _CtoCurrency = safe_cast<CCurrency^> (toCurrency);
        _CtoCurrency->Lock();
        QuantLib::Currency& _toCurrency = static_cast<QuantLib::Currency&> (_CtoCurrency->GetReference ()); 
        QuantLib::Date _evaluationDate = (QuantLib::Date)ValueHelper::Convert (evaluationDate);
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppCommodityPricingHelper)->calculateFxConversionFactor ( _fromCurrency,  _toCurrency,  _evaluationDate );   
        Double _nrv = (Double)ValueHelper::Convert (_rv);
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown std::exception"));
	}
    finally
    {
        if (_CfromCurrency != nullptr) _CfromCurrency->Unlock();
        if (_CtoCurrency != nullptr) _CtoCurrency->Unlock();
    }
}
Double Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CalculateUnitCost (Cephei::QL::Experimental::Commodities::ICommodityType^ commodityType, Cephei::QL::Experimental::Commodities::ICommodityUnitCost^ unitCost, Cephei::QL::ICurrency^ baseCurrency, Cephei::QL::Experimental::Commodities::IUnitOfMeasure^ baseUnitOfMeasure, DateTime evaluationDate)
{
    CCommodityType^ _CcommodityType;
    CCommodityUnitCost^ _CunitCost;
    CCurrency^ _CbaseCurrency;
    CUnitOfMeasure^ _CbaseUnitOfMeasure;
    try
    {
    	boost::detail::spinlock::scoped_lock lock (*_pSpinlock);
        _CcommodityType = safe_cast<CCommodityType^> (commodityType);
        _CcommodityType->Lock();
        QuantLib::CommodityType& _commodityType = static_cast<QuantLib::CommodityType&> (_CcommodityType->GetReference ()); 
        _CunitCost = safe_cast<CCommodityUnitCost^> (unitCost);
        _CunitCost->Lock();
        QuantLib::CommodityUnitCost& _unitCost = static_cast<QuantLib::CommodityUnitCost&> (_CunitCost->GetReference ()); 
        _CbaseCurrency = safe_cast<CCurrency^> (baseCurrency);
        _CbaseCurrency->Lock();
        QuantLib::Currency& _baseCurrency = static_cast<QuantLib::Currency&> (_CbaseCurrency->GetReference ()); 
        _CbaseUnitOfMeasure = safe_cast<CUnitOfMeasure^> (baseUnitOfMeasure);
        _CbaseUnitOfMeasure->Lock();
        QuantLib::UnitOfMeasure& _baseUnitOfMeasure = static_cast<QuantLib::UnitOfMeasure&> (_CbaseUnitOfMeasure->GetReference ()); 
        QuantLib::Date _evaluationDate = (QuantLib::Date)ValueHelper::Convert (evaluationDate);
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppCommodityPricingHelper)->calculateUnitCost ( _commodityType,  _unitCost,  _baseCurrency,  _baseUnitOfMeasure,  _evaluationDate );   
        Double _nrv = (Double)ValueHelper::Convert (_rv);
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown std::exception"));
	}
    finally
    {
        if (_CcommodityType != nullptr) _CcommodityType->Unlock();
        if (_CunitCost != nullptr) _CunitCost->Unlock();
        if (_CbaseCurrency != nullptr) _CbaseCurrency->Unlock();
        if (_CbaseUnitOfMeasure != nullptr) _CbaseUnitOfMeasure->Unlock();
    }
}
Double Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CalculateUomConversionFactor (Cephei::QL::Experimental::Commodities::ICommodityType^ commodityType, Cephei::QL::Experimental::Commodities::IUnitOfMeasure^ fromUnitOfMeasure, Cephei::QL::Experimental::Commodities::IUnitOfMeasure^ toUnitOfMeasure)
{
    CCommodityType^ _CcommodityType;
    CUnitOfMeasure^ _CfromUnitOfMeasure;
    CUnitOfMeasure^ _CtoUnitOfMeasure;
    try
    {
    	boost::detail::spinlock::scoped_lock lock (*_pSpinlock);
        _CcommodityType = safe_cast<CCommodityType^> (commodityType);
        _CcommodityType->Lock();
        QuantLib::CommodityType& _commodityType = static_cast<QuantLib::CommodityType&> (_CcommodityType->GetReference ()); 
        _CfromUnitOfMeasure = safe_cast<CUnitOfMeasure^> (fromUnitOfMeasure);
        _CfromUnitOfMeasure->Lock();
        QuantLib::UnitOfMeasure& _fromUnitOfMeasure = static_cast<QuantLib::UnitOfMeasure&> (_CfromUnitOfMeasure->GetReference ()); 
        _CtoUnitOfMeasure = safe_cast<CUnitOfMeasure^> (toUnitOfMeasure);
        _CtoUnitOfMeasure->Lock();
        QuantLib::UnitOfMeasure& _toUnitOfMeasure = static_cast<QuantLib::UnitOfMeasure&> (_CtoUnitOfMeasure->GetReference ()); 
    	QuantLib::Real _rv = (QuantLib::Real)(*_ppCommodityPricingHelper)->calculateUomConversionFactor ( _commodityType,  _fromUnitOfMeasure,  _toUnitOfMeasure );   
        Double _nrv = (Double)ValueHelper::Convert (_rv);
    	return _nrv;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown std::exception"));
	}
    finally
    {
        if (_CcommodityType != nullptr) _CcommodityType->Unlock();
        if (_CfromUnitOfMeasure != nullptr) _CfromUnitOfMeasure->Unlock();
        if (_CtoUnitOfMeasure != nullptr) _CtoUnitOfMeasure->Unlock();
    }
}
Cephei::QL::Experimental::Commodities::ICommodityPricingHelper^ Cephei::QL::Experimental::Commodities::CCommodityPricingHelper::CreatePricingPeriods (DateTime startDate, DateTime endDate, Cephei::QL::Experimental::Commodities::IQuantity^ quantity, QL::Experimental::Commodities::EnergyCommodity::DeliveryScheduleEnum deliverySchedule, QL::Experimental::Commodities::EnergyCommodity::QuantityPeriodicityEnum qtyPeriodicity, Cephei::QL::Experimental::Commodities::IPaymentTerm^ paymentTerm, Cephei::IVector<Cephei::QL::Experimental::Commodities::IPricingPeriod^>^ pricingPeriods)
{
    CQuantity^ _Cquantity;
    CPaymentTerm^ _CpaymentTerm;
    CoVector<Cephei::QL::Experimental::Commodities::IPricingPeriod^>^ _CpricingPeriods;
    try
    {
    	boost::detail::spinlock::scoped_lock lock (*_pSpinlock);
        QuantLib::Date _startDate = (QuantLib::Date)ValueHelper::Convert (startDate);
        QuantLib::Date _endDate = (QuantLib::Date)ValueHelper::Convert (endDate);
        _Cquantity = safe_cast<CQuantity^> (quantity);
        _Cquantity->Lock();
        QuantLib::Quantity& _quantity = static_cast<QuantLib::Quantity&> (_Cquantity->GetReference ()); 
        QuantLib::EnergyCommodity::DeliverySchedule _deliverySchedule = (QuantLib::EnergyCommodity::DeliverySchedule)deliverySchedule ;
        QuantLib::EnergyCommodity::QuantityPeriodicity _qtyPeriodicity = (QuantLib::EnergyCommodity::QuantityPeriodicity)qtyPeriodicity ;
        _CpaymentTerm = safe_cast<CPaymentTerm^> (paymentTerm);
        _CpaymentTerm->Lock();
        QuantLib::PaymentTerm& _paymentTerm = static_cast<QuantLib::PaymentTerm&> (_CpaymentTerm->GetReference ()); 
        _CpricingPeriods = safe_cast<CoVector<Cephei::QL::Experimental::Commodities::IPricingPeriod^>^> (pricingPeriods);
        _CpricingPeriods->Lock();
        INativeVector<Cephei::QL::Experimental::Commodities::IPricingPeriod^>^ _NCIpricingPeriods = _CpricingPeriods->getFeature (NativeFeature::shared_ptr);
        CPricingPeriodVector^ _NCpricingPeriods = safe_cast<CPricingPeriodVector^>(_NCIpricingPeriods);
        std::vector<boost::shared_ptr<QuantLib::PricingPeriod> >& _pricingPeriods = static_cast<std::vector<boost::shared_ptr<QuantLib::PricingPeriod> >&> (_NCpricingPeriods->GetShared ());
    	(*_ppCommodityPricingHelper)->createPricingPeriods ( _startDate,  _endDate,  _quantity,  _deliverySchedule,  _qtyPeriodicity,  _paymentTerm,  _pricingPeriods );
    	return this;
	}
    catch (QuantLib::Error& _error)
    {
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown quantlib error"));
        
    }
	catch (std::exception& _error)
	{
        if (_error.what())
		    throw gcnew NativeExcpetion (gcnew System::String(_error.what()));
        else
		    throw gcnew NativeExcpetion (gcnew System::String("Unknown std::exception"));
	}
    finally
    {
        if (_Cquantity != nullptr) _Cquantity->Unlock();
        if (_CpaymentTerm != nullptr) _CpaymentTerm->Unlock();
        if (_CpricingPeriods != nullptr) _CpricingPeriods->Unlock();
    }
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Factory class

Cephei::QL::Experimental::Commodities::ICommodityPricingHelper^ Cephei::QL::Experimental::Commodities::CCommodityPricingHelper_Factory::Create ()
{
    return gcnew CCommodityPricingHelper ();
}
